const path = require("path");
const webpack = require("webpack");
// webpack-chain：是一个用于创建和修改webpack配置的库，可以通过链式调用来配置
const webpackChain = require("webpack-chain");

exports.getConfig = () => {
  const config = new webpackChain();
  const EmpConfigPath = path.resolve(process.cwd(), "emp-cli.config.js");
  const EmpConfig = require(EmpConfigPath);
  const newConfig = processDefault(EmpConfig);
  config.merge(newConfig);
  // 将webpack-chain配置对象转为webpack配置对象
  return config.toConfig();
};

function processDefault(EmpConfig) {
  // 在项目中 emp-cli.config.js 配置文件使用的是server字段，可以自行修改
  const devServer = EmpConfig.server || {};
  // 删除 server 字段，因为webpack没有这个字段会报错
  delete EmpConfig.server;
  // 模块联邦配置
  const mfOptions = {
    filename: 'emp.js', // 指定当前容器为了对外提供模块联邦服务，生成的单独文件名emp.js
    /**
     * empShare字段是在项目中 emp-cli.config.js 的empShare字段配置的
     * {
     *      empShare: {
     *          // 必传，输出的模块名，是webpack打包后的全局变量名
     *          name: 'host' | 'remote',
     *          // 定义当前应用要暴露给其他应用的模块，这个参数是一个对象，key为别名，用于其他应用引用该模块，value为模块的相对路径
     *          exposes: {
     *              './App': './src/App'
     *          },
     *          // 定义其他远程应用的引用映射，这个参数是一个对象，key为别名，value为远程应用模块的url
     *          // host应用使用remote模块：import('@remote/App')
     *          remotes: {
     *              '@remote': 'remote@http://localhost:8001/remoteEntry.js'
     *          }
     *      }   
     * }
     */
    ...EmpConfig.empShare
  }
  delete EmpConfig.empShare
  // 这个 webpack-chain 的配置文件，不是webpack的，写法稍有不同（具体写法可以去webpack-chain的文档查看）
  return {
    // 项目根目录
    context: process.cwd(),
    mode: "development",
    devtool: false,
    devServer,
    plugin: {
      html: {
        plugin: require("html-webpack-plugin"),
        // 插件参数
        args: [
          {
            template: path.join(__dirname, "../template/index.html"),
          },
        ],
      },
      // 配置模块联邦插件
      mf: {
        plugin: require("webpack").container.ModuleFederationPlugin,
        args: [mfOptions]
      }
    },
    module: {
      rule: {
        compile: {
          test: /\.js$/,
          exclude: /node_modules/,
          use: {
            "babel-loader": {
              // require.resolve()：用于查找模块的绝对路径，返回指定模块的绝对路径字符串，但不会加载该模块。
              loader: require.resolve("babel-loader"),
              options: {
                presets: [require.resolve("@babel/preset-env"), require.resolve("@babel/preset-react")],
              },
            },
          },
        },
      },
    },
    ...EmpConfig,
  };
}
